package be.sc.classicnetwork.controller;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.propertyeditors.CustomNumberEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import be.sc.classicnetwork.controller.beans.EntityPropertyEditor;
import be.sc.classicnetwork.model.Contact;
import be.sc.classicnetwork.model.Image;
import be.sc.classicnetwork.model.Location;
import be.sc.classicnetwork.model.Make;
import be.sc.classicnetwork.model.Site;
import be.sc.classicnetwork.model.Type;
import be.sc.classicnetwork.service.ServiceLocator;

/**
 * Abstract Form controller.
 */
public class AbstractFormController extends SimpleFormController {

    private ServiceLocator serviceLocator;

    private TaskExecutor taskExecutor;

    /**
     * @see org.springframework.web.servlet.mvc.AbstractFormController#handleInvalidSubmit(javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse)
     */
    @Override
    protected ModelAndView handleInvalidSubmit(HttpServletRequest request, HttpServletResponse response)
	    throws Exception {
	BindException errors = getErrorsForNewForm(request);
	errors.reject("duplicateFormSubmission", "Duplicate form submission");
	return showForm(request, response, errors);
    }

    /**
     * @see org.springframework.web.servlet.mvc.BaseCommandController#initBinder(javax.servlet.http.HttpServletRequest,
     *      org.springframework.web.bind.ServletRequestDataBinder)
     */
    @Override
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
	// bind images
	binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());

	// bind Numbers
	binder.registerCustomEditor(Integer.class, new CustomNumberEditor(Integer.class, true));
	binder.registerCustomEditor(Double.class, new CustomNumberEditor(Double.class, true));
	binder.registerCustomEditor(Make.class, new EntityPropertyEditor(Make.class));
	binder.registerCustomEditor(Site.class, new EntityPropertyEditor(Site.class));
	binder.registerCustomEditor(Type.class, new EntityPropertyEditor(Type.class));
	binder.registerCustomEditor(Image.class, new EntityPropertyEditor(Image.class));
	binder.registerCustomEditor(Contact.class, new EntityPropertyEditor(Contact.class));
	binder.registerCustomEditor(Location.class, new EntityPropertyEditor(Location.class));
	binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }

    /**
     * getMaxIndex.
     */
    @SuppressWarnings("unchecked")
    protected int getMaxIndex(HttpServletRequest request, String property) {
	int maxIndex = -1;
	for (Enumeration<String> parameters = request.getParameterNames(); parameters.hasMoreElements();) {
	    String parameterName = parameters.nextElement();
	    if (parameterName.startsWith(property)) {
		int startIndex = parameterName.indexOf("[", property.length());
		int endIndex = parameterName.indexOf("]", property.length());
		if ((startIndex == -1) || (endIndex == -1)) {
		    return (-1);
		}
		int index = Integer.parseInt(parameterName.substring((startIndex + 1), endIndex));
		if (index > maxIndex) {
		    maxIndex = index;
		}
	    }
	}
	return (maxIndex);
    }

    /**
     * Sets the specified message in the request..
     */
    protected void showMessage(HttpServletRequest request, String message) {
	request.setAttribute("message", message);
    }

    public TaskExecutor getTaskExecutor() {
	return taskExecutor;
    }

    public void setTaskExecutor(TaskExecutor taskExecutor) {
	this.taskExecutor = taskExecutor;
    }

    public ServiceLocator getServiceLocator() {
	return serviceLocator;
    }

    public void setServiceLocator(ServiceLocator serviceLocator) {
	this.serviceLocator = serviceLocator;
    }

}
